bitkeeper revision 1.552 (3fa6715f0LpnznAkmX17sTFtzPmomQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Mon, 3 Nov 2003 15:16:47 +0000 (15:16 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Mon, 3 Nov 2003 15:16:47 +0000 (15:16 +0000)
Many files:
  Clean up domain building interface ready for suspend/resume.

13 files changed:
tools/internal/dom0_defs.h
tools/internal/xi_build.c
tools/internal/xi_list.c
xen/arch/i386/mm.c
xen/arch/i386/traps.c
xen/common/debug.c
xen/common/dom0_ops.c
xen/common/domain.c
xen/common/schedule.c
xen/include/asm-i386/processor.h
xen/include/hypervisor-ifs/dom0_ops.h
xen/include/xeno/sched.h
xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h

index bea8981bee44ea90f2f07b02b86af742b33b0564..13162534d20bd2f0a98bce8e7af0543a8926d83a 100644 (file)
@@ -98,7 +98,7 @@ static inline int do_dom0_op(dom0_op_t *op)
 
     if ( do_xen_hypercall(&hypercall) < 0 )
     {
-        if ( errno == EINVAL )
+        if ( errno == EACCES )
             fprintf(stderr, "Dom0 operation failed -- need to"
                     " rebuild the user-space tool set?\n");
         goto out2;
index f18f9941246778a7149fb6c43731a69610bd9321..1fb3be27487c470be6b1000fdea80e607191b9fa 100644 (file)
@@ -68,7 +68,7 @@ static int send_pgupdates(mmu_update_t *updates, int nr_updates)
 
 /* Read the kernel header, extracting the image size and load address. */
 static int read_kernel_header(int fd, long dom_size, 
-                             unsigned long * load_addr, size_t * ksize)
+                              unsigned long * load_addr, size_t * ksize)
 {
     char signature[8];
     char status[1024];
@@ -77,7 +77,7 @@ static int read_kernel_header(int fd, long dom_size,
     if ( fstat(fd, &stat) < 0 )
     {
         PERROR("Cannot stat the kernel image");
-       return -1;
+        return -1;
     }
 
     /* Double the kernel image size to account for dynamic memory usage etc. */
@@ -86,7 +86,7 @@ static int read_kernel_header(int fd, long dom_size,
         sprintf(status, "Kernel image size %ld larger than requested "
                 "domain size %ld\n Terminated.\n", stat.st_size, dom_size);
         ERROR(status);
-       return -1;
+        return -1;
     }
     
     read(fd, signature, SIG_LEN);
@@ -94,7 +94,7 @@ static int read_kernel_header(int fd, long dom_size,
     {
         ERROR("Kernel image does not contain required signature.\n"
               "Terminating.\n");
-       return -1;
+        return -1;
     }
 
     /* Read the load address which immediately follows the Xeno signature. */
@@ -147,7 +147,7 @@ static int copy_to_domain_page(unsigned long dst_pfn, void *src_page)
 static int setup_guestos(
     int dom, int kernel_fd, int initrd_fd, unsigned long tot_pages,
     unsigned long virt_load_addr, size_t ksize, 
-    dom0_builddomain_t *builddomain)
+    dom0_builddomain_t *builddomain, int argc, char **argv, int args_start)
 {
     l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
     l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
@@ -158,6 +158,9 @@ static int setup_guestos(
     unsigned long l1tab = 0;
     unsigned long num_pgt_updates = 0;
     unsigned long count, pt_start, i, j;
+    unsigned long initrd_addr = 0, initrd_len = 0;
+    start_info_t *start_info;
+    int cmd_len;
 
     memset(builddomain, 0, sizeof(*builddomain));
 
@@ -169,14 +172,14 @@ static int setup_guestos(
     pgt_update_arr = pgt_updates;
     if ( (pgt_update_arr == NULL) || (page_array == NULL) )
     {
-       PERROR("Could not allocate memory");
-       goto error_out;
+        PERROR("Could not allocate memory");
+        goto error_out;
     }
 
     if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
     {
-       PERROR("Could not get the page frame list");
-       goto error_out;
+        PERROR("Could not get the page frame list");
+        goto error_out;
     }
 
     /* Load the guest OS image. */
@@ -196,15 +199,15 @@ static int setup_guestos(
     /* Load the initial ramdisk image. */
     if ( initrd_fd >= 0 )
     {
-       struct stat stat;
-       unsigned long isize;
+        struct stat stat;
+        unsigned long isize;
 
-       if ( fstat(initrd_fd, &stat) < 0 )
+        if ( fstat(initrd_fd, &stat) < 0 )
         {
             PERROR("Could not stat the initrd image");
             goto error_out;
-       }
-       isize = stat.st_size;
+        }
+        isize = stat.st_size;
         if ( ((isize + ksize) * 2) > (tot_pages << PAGE_SHIFT) )
         {
             ERROR("Kernel + initrd too big to safely fit in domain memory");
@@ -212,8 +215,8 @@ static int setup_guestos(
         }
 
         /* 'i' is 'ksize' rounded up to a page boundary. */
-        builddomain->virt_mod_addr = virt_load_addr + i;
-        builddomain->virt_mod_len  = isize;
+        initrd_addr = virt_load_addr + i;
+        initrd_len  = isize;
 
         for ( j = 0; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
         {
@@ -246,7 +249,7 @@ static int setup_guestos(
      */
     l2tab = page_array[alloc_index] << PAGE_SHIFT;
     alloc_index--;
-    builddomain->l2_pgt_addr = l2tab;
+    builddomain->ctxt.pt_base = l2tab;
 
     /*
      * Pin down l2tab addr as page dir page - causes hypervisor to provide
@@ -271,7 +274,7 @@ static int setup_guestos(
                 goto error_out;
             memset(vl1tab, 0, PAGE_SIZE);
             alloc_index--;
-                       
+               
             vl1e = vl1tab + l1_table_offset(virt_load_addr + 
                                             (count << PAGE_SHIFT));
 
@@ -295,21 +298,40 @@ static int setup_guestos(
         {
             pgt_updates->ptr = (unsigned long)vl1e;
             pgt_updates->val = 
-               ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
+                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
             pgt_updates++;
             num_pgt_updates++;
             vl1e++;
         }
 
         pgt_updates->ptr = 
-           (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
         pgt_updates->val = count;
         pgt_updates++;
         num_pgt_updates++;
     }
 
     builddomain->virt_startinfo_addr =
-        virt_load_addr + ((alloc_index-1)<<PAGE_SHIFT);
+        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
+
+    start_info = map_pfn(page_array[alloc_index-1]);
+    memset(start_info, 0, sizeof(*start_info));
+    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
+    start_info->mod_start   = initrd_addr;
+    start_info->mod_len     = initrd_len;
+    cmd_len = 0;
+    for ( i = args_start; i < argc; i++ )
+    {
+        if ( cmd_len + strlen(argv[i]) > MAX_CMD_LEN - 1 ) 
+        {
+            ERROR("Size of image boot params too big!\n");
+            break;
+        }
+        strcat(start_info->cmd_line, argv[i]);
+        strcat(start_info->cmd_line, " ");
+        cmd_len += strlen(argv[i] + 1);
+    }
+    unmap_pfn(start_info);
 
     /* Send the page update requests down to the hypervisor. */
     if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
@@ -321,9 +343,9 @@ static int setup_guestos(
 
  error_out:
     if ( page_array == NULL )
-       free(page_array);
+        free(page_array);
     if ( pgt_update_arr == NULL )
-       free(pgt_update_arr);
+        free(pgt_update_arr);
     return -1;
 }
 
@@ -338,12 +360,11 @@ int main(int argc, char **argv)
     unsigned long load_addr;
     long tot_pages;
     int kernel_fd, initrd_fd = -1;
-    int count;
-    int cmd_len;
     int args_start = 4;
     char initrd_name[1024];
     int domain_id;
-    int rc;
+    int rc, i;
+    full_execution_context_t *ctxt;
 
     if ( argv[0] != NULL ) 
         argv0 = argv[0];
@@ -365,62 +386,98 @@ int main(int argc, char **argv)
     if ( (tot_pages = get_tot_pages(domain_id)) < 0 )
     {
         PERROR("Could not find total pages for domain");
-       return 1;
+        return 1;
     }
 
     kernel_fd = open(argv[2], O_RDONLY);
     if ( kernel_fd < 0 )
     {
         PERROR("Could not open kernel image");
-       return 1;
+        return 1;
     }
 
     rc = read_kernel_header(kernel_fd,
-                           tot_pages << (PAGE_SHIFT - 10), 
-                           &load_addr, &ksize);
+                            tot_pages << (PAGE_SHIFT - 10), 
+                            &load_addr, &ksize);
     if ( rc < 0 )
-       return 1;
+        return 1;
     
     if( (argc > args_start) && 
         (strncmp("initrd=", argv[args_start], 7) == 0) )
     {
-       strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) );
-       initrd_name[sizeof(initrd_name)-1] = 0;
-       printf("initrd present, name = %s\n", initrd_name );
-       args_start++;
+        strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) );
+        initrd_name[sizeof(initrd_name)-1] = 0;
+        printf("initrd present, name = %s\n", initrd_name );
+        args_start++;
         
-       initrd_fd = open(initrd_name, O_RDONLY);
-       if ( initrd_fd < 0 )
+        initrd_fd = open(initrd_name, O_RDONLY);
+        if ( initrd_fd < 0 )
         {
             PERROR("Could not open the initial ramdisk image");
-           return 1;
-       }
+            return 1;
+        }
     }
 
     if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages,
-                       load_addr, ksize, &launch_op.u.builddomain) < 0 )
+                       load_addr, ksize, &launch_op.u.builddomain,
+                       argc, argv, args_start) < 0 )
         return 1;
 
     if ( initrd_fd >= 0 )
-       close(initrd_fd);
+        close(initrd_fd);
     close(kernel_fd);
 
-    launch_op.u.builddomain.domain         = domain_id;
-    launch_op.u.builddomain.virt_load_addr = load_addr;
-    launch_op.u.builddomain.num_vifs       = atoi(argv[3]);
-    launch_op.u.builddomain.cmd_line[0]    = '\0';
-    cmd_len = 0;
-    for ( count = args_start; count < argc; count++ )
+    ctxt = &launch_op.u.builddomain.ctxt;
+
+    /*
+     * Initial register values:
+     *  DS,ES,FS,GS = FLAT_RING1_DS
+     *       CS:EIP = FLAT_RING1_CS:start_pc
+     *       SS:ESP = FLAT_RING1_DS:start_stack
+     *          ESI = start_info
+     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
+     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
+     */
+    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
+    ctxt->i386_ctxt.es = FLAT_RING1_DS;
+    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
+    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
+    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
+    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
+    ctxt->i386_ctxt.eip = load_addr;
+    ctxt->i386_ctxt.esp = launch_op.u.builddomain.virt_startinfo_addr;
+    ctxt->i386_ctxt.esi = launch_op.u.builddomain.virt_startinfo_addr;
+    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
+
+    /* FPU is set up to default initial state. */
+    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
+
+    /* Virtual IDT is empty at start-of-day. */
+    for ( i = 0; i < 256; i++ )
     {
-        if ( cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1 ) 
-        {
-            ERROR("Size of image boot params too big!\n");
-            break;
-        }
-        strcat(launch_op.u.builddomain.cmd_line, argv[count]);
-        strcat(launch_op.u.builddomain.cmd_line, " ");
-        cmd_len += strlen(argv[count] + 1);
+        ctxt->trap_ctxt[i].vector = i;
+        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
     }
+    ctxt->fast_trap_idx = 0;
+
+    /* No LDT. */
+    ctxt->ldt_ents = 0;
+    
+    /* Use the default Xen-provided GDT. */
+    ctxt->gdt_ents = 0;
+
+    /* Ring 1 stack is the initial stack. */
+    ctxt->ring1_ss  = FLAT_RING1_DS;
+    ctxt->ring1_esp = launch_op.u.builddomain.virt_startinfo_addr;
+
+    /* No debugging. */
+    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
+
+    /* Domain time counts from zero. */
+    ctxt->domain_time = 0;
+
+    launch_op.u.builddomain.domain   = domain_id;
+    launch_op.u.builddomain.num_vifs = atoi(argv[3]);
 
     launch_op.cmd = DOM0_BUILDDOMAIN;
     rc = do_dom0_op(&launch_op);
index 73df092b1d0ba7fa3168163680f0297052a34d69..562d5c302ad35396fba9d175e1c600ad7bcc3e51 100644 (file)
@@ -30,12 +30,11 @@ static char *statestr(int state)
 {
     switch ( state )
     {
-    case  0: return "RUNNING";
-    case  1: return "INTERRUPTIBLE";
-    case  2: return "UNINTERRUPTIBLE";
-    case  4: return "WAIT";
-    case  8: return "SUSPENDED";
-    case 16: return "DYING";
+    case 0: return "RUNNING";
+    case 1: return "INTERRUPTIBLE";
+    case 2: return "UNINTERRUPTIBLE";
+    case 4: return "STOPPED";
+    case 8: return "DYING";
     default: return "UNKNOWN";
     }
     return NULL;
index cac87b6ef2007333987413bef0e7bcb0371b517d..419f4cb1b312426283ff301e8ac7ba3f6b0d7f9c 100644 (file)
@@ -207,21 +207,18 @@ int check_descriptor(unsigned long a, unsigned long b)
 }
 
 
-long do_set_gdt(unsigned long *frame_list, unsigned int entries)
+long set_gdt(struct task_struct *p, 
+             unsigned long *frames,
+             unsigned int entries)
 {
     /* NB. There are 512 8-byte entries per GDT page. */
     unsigned int i, j, nr_pages = (entries + 511) / 512;
-    unsigned long frames[16], pfn, *gdt_page, flags;
+    unsigned long pfn, *gdt_page, flags;
     long ret = -EINVAL;
     struct pfn_info *page;
+    struct desc_struct *vgdt;
 
-    if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) 
-        return -EINVAL;
-
-    if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
-        return -EFAULT;
-
-    spin_lock_irqsave(&current->page_lock, flags);
+    spin_lock_irqsave(&p->page_lock, flags);
 
     /* Check the new GDT. */
     for ( i = 0; i < nr_pages; i++ )
@@ -230,7 +227,7 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
             goto out;
         
         page = frame_table + frames[i];
-        if ( (page->flags & PG_domain_mask) != current->domain )
+        if ( (page->flags & PG_domain_mask) != p->domain )
             goto out;
 
         if ( (page->flags & PG_type_mask) != PGT_gdt_page )
@@ -250,12 +247,12 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
     /* Tear down the old GDT. */
     for ( i = 0; i < 16; i++ )
     {
-        pfn = l1_pgentry_to_pagenr(current->mm.perdomain_pt[i]);
-        current->mm.perdomain_pt[i] = mk_l1_pgentry(0);
+        pfn = l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]);
+        p->mm.perdomain_pt[i] = mk_l1_pgentry(0);
         if ( pfn == 0 ) continue;
         page = frame_table + pfn;
         ASSERT((page->flags & PG_type_mask) == PGT_gdt_page);
-        ASSERT((page->flags & PG_domain_mask) == current->domain);
+        ASSERT((page->flags & PG_domain_mask) == p->domain);
         ASSERT((page->type_count != 0) && (page->tot_count != 0));
         put_page_type(page);
         put_page_tot(page);
@@ -264,7 +261,7 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
     /* Install the new GDT. */
     for ( i = 0; i < nr_pages; i++ )
     {
-        current->mm.perdomain_pt[i] =
+        p->mm.perdomain_pt[i] =
             mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
         
         page = frame_table + frames[i];
@@ -274,21 +271,42 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
         get_page_tot(page);
     }
 
-    local_flush_tlb();
-
     /* Copy reserved GDT entries to the new GDT. */
-    memcpy((struct desc_struct *)GDT_VIRT_START + FIRST_RESERVED_GDT_ENTRY, 
+    vgdt = map_domain_mem(frames[i] << PAGE_SHIFT);
+    memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, 
            gdt_table + FIRST_RESERVED_GDT_ENTRY, 
            NR_RESERVED_GDT_ENTRIES*8);
-    
-    SET_GDT_ADDRESS(current, GDT_VIRT_START);
-    SET_GDT_ENTRIES(current, (entries*8)-1);
-    __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
+    unmap_domain_mem(vgdt);
+
+    SET_GDT_ADDRESS(p, GDT_VIRT_START);
+    SET_GDT_ENTRIES(p, (entries*8)-1);
 
     ret = 0; /* success */
 
  out:
-    spin_unlock_irqrestore(&current->page_lock, flags);
+    spin_unlock_irqrestore(&p->page_lock, flags);
+    return ret;
+}
+
+
+long do_set_gdt(unsigned long *frame_list, unsigned int entries)
+{
+    unsigned int nr_pages = (entries + 511) / 512;
+    unsigned long frames[16];
+    long ret;
+
+    if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) 
+        return -EINVAL;
+    
+    if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
+        return -EFAULT;
+
+    if ( (ret = set_gdt(current, frames, entries)) == 0 )
+    {
+        local_flush_tlb();
+        __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
+    }
+
     return ret;
 }
 
index 33bc451d03ba23214fe07e5a28dabf1fb84c41a6..9065aacd0392f7a83925e5da490dbfd853a72d97 100644 (file)
@@ -692,15 +692,16 @@ long do_set_callbacks(unsigned long event_selector,
 }
 
 
-long do_set_fast_trap(int idx)
+long set_fast_trap(struct task_struct *p, int idx)
 {
     trap_info_t *ti;
 
     /* Index 0 is special: it disables fast traps. */
     if ( idx == 0 )
     {
-        CLEAR_FAST_TRAP(&current->thread);
-        SET_DEFAULT_FAST_TRAP(&current->thread);
+        if ( p == current )
+            CLEAR_FAST_TRAP(&p->thread);
+        SET_DEFAULT_FAST_TRAP(&p->thread);
         return 0;
     }
 
@@ -712,7 +713,7 @@ long do_set_fast_trap(int idx)
     if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) 
         return -1;
 
-    ti = current->thread.traps + idx;
+    ti = p->thread.traps + idx;
 
     /*
      * We can't virtualise interrupt gates, as there's no way to get
@@ -721,19 +722,27 @@ long do_set_fast_trap(int idx)
     if ( TI_GET_IF(ti) )
         return -1;
 
-    CLEAR_FAST_TRAP(&current->thread);
+    if ( p == current )
+        CLEAR_FAST_TRAP(&p->thread);
 
-    current->thread.fast_trap_idx    = idx;
-    current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
-    current->thread.fast_trap_desc.b = 
+    p->thread.fast_trap_idx    = idx;
+    p->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
+    p->thread.fast_trap_desc.b = 
         (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
 
-    SET_FAST_TRAP(&current->thread);
+    if ( p == current )
+        SET_FAST_TRAP(&p->thread);
 
     return 0;
 }
 
 
+long do_set_fast_trap(int idx)
+{
+    return set_fast_trap(current, idx);
+}
+
+
 long do_fpu_taskswitch(void)
 {
     current->flags |= PF_GUEST_STTS;
index c20c5b21b58b68a67689200cc3a75d60bd1566b8..1d701e869b8138976815f9a8d7cc33bc8fd61eb3 100644 (file)
@@ -61,7 +61,7 @@ void pdb_do_debug (dom0_op_t *op)
 
            if (p != NULL)
            {
-               if (p->state != TASK_SUSPENDED)
+               if (p->state != TASK_STOPPED)
                {
                    cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
                    hyp_event_notify(cpu_mask);
index 17dbf1d4de896f620d4694080918f6aa97d500ec..b798c70022e06612a474237fecbf763d4ce09ce2 100644 (file)
@@ -93,7 +93,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
         return -EFAULT;
 
     if ( op.interface_version != DOM0_INTERFACE_VERSION )
-        return -EINVAL;
+        return -EACCES;
 
     switch ( op.cmd )
     {
@@ -249,6 +249,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     { 
         struct task_struct *p = &idle0_task;
         u_long flags;
+        int i;
 
         read_lock_irqsave (&tasklist_lock, flags);
 
@@ -271,11 +272,46 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
             op.u.getdomaininfo.mcu_advance = p->mcu_advance;
             op.u.getdomaininfo.tot_pages   = p->tot_pages;
             op.u.getdomaininfo.cpu_time    = p->cpu_time;
-            memcpy(&op.u.getdomaininfo.ctxt, 
-                   &p->shared_info->execution_context,
-                   sizeof(execution_context_t));
+            if ( p->state == TASK_STOPPED )
+            {
+                rmb(); /* Ensure that we see saved register state. */
+                memcpy(&op.u.getdomaininfo.ctxt.i386_ctxt, 
+                       &p->shared_info->execution_context,
+                       sizeof(p->shared_info->execution_context));
+                memcpy(&op.u.getdomaininfo.ctxt.i387_ctxt,
+                       &p->thread.i387,
+                       sizeof(p->thread.i387));
+                memcpy(&op.u.getdomaininfo.ctxt.trap_ctxt,
+                       p->thread.traps,
+                       sizeof(p->thread.traps));
+                if ( (p->thread.fast_trap_desc.a == 0) &&
+                     (p->thread.fast_trap_desc.b == 0) )
+                    op.u.getdomaininfo.ctxt.fast_trap_idx = 0;
+                else
+                    op.u.getdomaininfo.ctxt.fast_trap_idx = 
+                        p->thread.fast_trap_idx;
+                op.u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base;
+                op.u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents;
+                op.u.getdomaininfo.ctxt.gdt_ents = 0;
+                if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START )
+                {
+                    for ( i = 0; i < 16; i++ )
+                        op.u.getdomaininfo.ctxt.gdt_frames[i] = 
+                            l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]);
+                    op.u.getdomaininfo.ctxt.gdt_ents = 
+                        (GET_GDT_ENTRIES(p) + 1) >> 3;
+                }
+                op.u.getdomaininfo.ctxt.ring1_ss  = p->thread.ss1;
+                op.u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1;
+                op.u.getdomaininfo.ctxt.pt_base   = 
+                    pagetable_val(p->mm.pagetable);
+                memcpy(op.u.getdomaininfo.ctxt.debugreg, 
+                       p->thread.debugreg, 
+                       sizeof(p->thread.debugreg));
+                op.u.getdomaininfo.ctxt.domain_time = 
+                    p->shared_info->domain_time;
+            }
         }
-
         read_unlock_irqrestore(&tasklist_lock, flags);
         copy_to_user(u_dom0_op, &op, sizeof(op));
     }
index 5005cc9f47762f495785317a25547b53851ef06c..d8963c0e7168c401e875680a7c8520635f021d3f 100644 (file)
@@ -18,6 +18,8 @@
 #include <xeno/console.h>
 #include <xeno/vbd.h>
 
+#include <asm/i387.h>
+
 /*
  * NB. No ring-3 access in initial guestOS pagetables. Note that we allow
  * ring-3 privileges in the page directories, so that the guestOS may later
@@ -186,7 +188,7 @@ long kill_other_domain(unsigned int dom, int force)
     p = find_domain_by_id(dom);
     if ( p == NULL ) return -ESRCH;
 
-    if ( p->state == TASK_SUSPENDED )
+    if ( p->state == TASK_STOPPED )
     {
         __kill_domain(p);
     }
@@ -207,7 +209,12 @@ long kill_other_domain(unsigned int dom, int force)
 
 void stop_domain(void)
 {
-    set_current_state(TASK_SUSPENDED);
+    memcpy(&current->shared_info->execution_context, 
+           get_execution_context(), 
+           sizeof(execution_context_t));
+    unlazy_fpu(current);
+    wmb(); /* All CPUs must see saved info in state TASK_STOPPED. */
+    set_current_state(TASK_STOPPED);
     clear_bit(_HYP_EVENT_STOP, &current->hyp_events);
     __enter_scheduler();
 }
@@ -220,7 +227,7 @@ long stop_other_domain(unsigned int dom)
     p = find_domain_by_id (dom);
     if ( p == NULL) return -ESRCH;
     
-    if ( p->state != TASK_SUSPENDED )
+    if ( p->state != TASK_STOPPED )
     {
         cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
         hyp_event_notify(cpu_mask);
@@ -328,25 +335,10 @@ void release_task(struct task_struct *p)
 /* final_setup_guestos is used for final setup and launching of domains other
  * than domain 0. ie. the domains that are being built by the userspace dom0
  * domain builder.
- *
- * Initial load map:
- *  start_address:
- *     OS image
- *      ....
- *  stack_start:
- *  start_info:
- *      <one page>
- *  page tables:
- *      <enough pages>
- *  end_address:
- *  shared_info:
- *      <one page>
  */
-
 int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
 {
     start_info_t * virt_startinfo_addr;
-    unsigned long virt_stack_addr;
     unsigned long phys_l2tab;
     net_ring_t *shared_rings;
     net_vif_t *net_vif;
@@ -355,19 +347,43 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
     if ( (p->flags & PF_CONSTRUCTED) )
         return -EINVAL;
 
+    memcpy(&p->shared_info->execution_context,
+           &builddomain->ctxt.i386_ctxt,
+           sizeof(p->shared_info->execution_context));
+    memcpy(&p->thread.i387,
+           &builddomain->ctxt.i387_ctxt,
+           sizeof(p->thread.i387));
+    memcpy(p->thread.traps,
+           &builddomain->ctxt.trap_ctxt,
+           sizeof(p->thread.traps));
+    SET_DEFAULT_FAST_TRAP(&p->thread);
+    (void)set_fast_trap(p, builddomain->ctxt.fast_trap_idx);
+    p->mm.ldt_base = builddomain->ctxt.ldt_base;
+    p->mm.ldt_ents = builddomain->ctxt.ldt_ents;
+    SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
+    SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
+    if ( builddomain->ctxt.gdt_ents != 0 )
+        (void)set_gdt(p,
+                      builddomain->ctxt.gdt_frames,
+                      builddomain->ctxt.gdt_ents);
+    p->thread.ss1  = builddomain->ctxt.ring1_ss;
+    p->thread.esp1 = builddomain->ctxt.ring1_esp;
+    memcpy(p->thread.debugreg,
+           builddomain->ctxt.debugreg,
+           sizeof(p->thread.debugreg));
+    
     /* NB. Page base must already be pinned! */
-    phys_l2tab = builddomain->l2_pgt_addr;
+    phys_l2tab = builddomain->ctxt.pt_base;
     p->mm.pagetable = mk_pagetable(phys_l2tab);
     get_page_type(&frame_table[phys_l2tab>>PAGE_SHIFT]);
     get_page_tot(&frame_table[phys_l2tab>>PAGE_SHIFT]);
 
     /* set up the shared info structure */
     update_dom_time(p->shared_info);
-    p->shared_info->domain_time = 0;
+    p->shared_info->domain_time = builddomain->ctxt.domain_time;
 
     /* we pass start info struct to guest os as function parameter on stack */
     virt_startinfo_addr = (start_info_t *)builddomain->virt_startinfo_addr;
-    virt_stack_addr = (unsigned long)virt_startinfo_addr;       
 
     /* we need to populate start_info struct within the context of the
      * new domain. thus, temporarely install its pagetables.
@@ -376,17 +392,8 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
     __asm__ __volatile__ ( 
         "mov %%eax,%%cr3" : : "a" (pagetable_val(p->mm.pagetable)));
 
-    memset(virt_startinfo_addr, 0, sizeof(*virt_startinfo_addr));
     virt_startinfo_addr->nr_pages = p->tot_pages;
-    virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info);
-    virt_startinfo_addr->pt_base = builddomain->virt_load_addr + 
-                    ((p->tot_pages - 1) << PAGE_SHIFT);
-   
-    /* module size and length */
-
-    virt_startinfo_addr->mod_start = builddomain->virt_mod_addr;
-    virt_startinfo_addr->mod_len   = builddomain->virt_mod_len;
-
+    virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info);   
     virt_startinfo_addr->dom_id = p->domain;
     virt_startinfo_addr->flags  = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
 
@@ -409,9 +416,6 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
     /* Add block io interface */
     virt_startinfo_addr->blk_ring = virt_to_phys(p->blk_ring_base);
 
-    /* Copy the command line */
-    strcpy(virt_startinfo_addr->cmd_line, builddomain->cmd_line);
-
     /* Reinstate the caller's page tables. */
     __asm__ __volatile__ (
         "mov %%eax,%%cr3" : : "a" (pagetable_val(current->mm.pagetable)));    
@@ -419,11 +423,6 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
 
     p->flags |= PF_CONSTRUCTED;
     
-    new_thread(p, 
-               (unsigned long)builddomain->virt_load_addr, 
-               (unsigned long)virt_stack_addr, 
-               (unsigned long)virt_startinfo_addr);
-
     return 0;
 }
 
index 2825e71efb9aa0e6ed5625cec3bab56f6166bc5f..d56bf0041287541c47a4a588700448fe3bcb803e 100644 (file)
@@ -116,7 +116,7 @@ static void __calc_evt(struct task_struct *p)
  */
 void sched_add_domain(struct task_struct *p) 
 {
-    p->state       = TASK_SUSPENDED;
+    p->state       = TASK_STOPPED;
     p->mcu_advance = MCU_ADVANCE;
 
     if ( p->domain == IDLE_DOMAIN_ID )
@@ -379,11 +379,10 @@ asmlinkage void __enter_scheduler(void)
             break;
         }
     case TASK_UNINTERRUPTIBLE:
-    case TASK_WAIT:
     case TASK_DYING:
-    case TASK_SUSPENDED:
+    case TASK_STOPPED:
     default:
-        /* done if not running. Else, continue */
+        /* Done if not running. Else continue. */
         goto deschedule_done;
     case TASK_RUNNING:;
     }
index 3f3c8c4ba1025cb06a2fd1b1632e5ac19bf62ed2..4022ef5fdef717cb89ca45936c2f774fddfd9e0c 100644 (file)
@@ -14,6 +14,7 @@
 #include <xeno/config.h>
 #include <hypervisor-ifs/hypervisor-if.h>
 
+struct task_struct;
 
 /*
  * Default implementation of macro that returns current
@@ -381,6 +382,8 @@ extern struct desc_struct *idt_tables[];
     (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
      &((_p)->fast_trap_desc), 8))
 
+long set_fast_trap(struct task_struct *p, int idx);
+
 #define INIT_THREAD  {                                         \
        0, 0,                                                   \
        { [0 ... 7] = 0 },      /* debugging registers */       \
@@ -430,7 +433,9 @@ struct mm_struct {
 #define GET_GDT_ENTRIES(_p)     ((*(u16 *)((_p)->mm.gdt + 0)))
 #define GET_GDT_ADDRESS(_p)     ((*(u32 *)((_p)->mm.gdt + 2)))
 
-struct task_struct;
+long set_gdt(struct task_struct *p, 
+             unsigned long *frames, 
+             unsigned int entries);
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
index ff07461f8bf367546ace15f692261a51d1abe2dc..cd187641068ae5bcab05024465f5b21970fcabd2 100644 (file)
@@ -17,7 +17,7 @@
  * This makes sure that old versions of dom0 tools will stop working in a
  * well-defined way (rather than crashing the machine, for instance).
  */
-#define DOM0_INTERFACE_VERSION   0xAAAA0001
+#define DOM0_INTERFACE_VERSION   0xAAAA0002
 
 
 /*
@@ -35,6 +35,7 @@ typedef struct full_execution_context_st
     unsigned long ring1_ss, ring1_esp;      /* Virtual TSS (only SS1/ESP1)  */
     unsigned long pt_base;                  /* CR3 (pagetable base)         */
     unsigned long debugreg[8];              /* DB0-DB7 (debug registers)    */
+    u64           domain_time;              /* Domain virtual time          */
 } full_execution_context_t;
 
 #define MAX_CMD_LEN       256
@@ -88,13 +89,8 @@ typedef struct dom0_builddomain_st
 {
     /* IN variables. */
     unsigned int  domain;
-    unsigned long l2_pgt_addr;
-    unsigned long virt_load_addr;
     unsigned long virt_startinfo_addr;
-    unsigned int num_vifs;
-    char cmd_line[MAX_CMD_LEN];
-    unsigned long virt_mod_addr;
-    unsigned long virt_mod_len;
+    unsigned int  num_vifs;
     full_execution_context_t ctxt;
 } dom0_builddomain_t;
 
index 8265726fd83132d8a23b0bcb54b5180a7ca0a844..6775071a315c0ec3cbcc3ea37c04211570752667 100644 (file)
@@ -146,20 +146,18 @@ struct task_struct
  *                       or expiring timer
  * TASK_UNINTERRUPTIBLE: Domain is blocked but may not be woken up by an
  *                       arbitrary event or timer.
- * TASK_WAIT:            Domains CPU allocation expired.
- * TASK_SUSPENDED:       Domain is suspended (startofday or pervasive debugger)
+ * TASK_STOPPED:         Domain is sopped.
  * TASK_DYING:           Domain is about to cross over to the land of the dead.
  *
  * If you update these then please update the mapping to text names in
  * xi_list.
  */
 
-#define TASK_RUNNING            0
-#define TASK_INTERRUPTIBLE      1
-#define TASK_UNINTERRUPTIBLE    2
-#define TASK_WAIT               4
-#define TASK_SUSPENDED          8
-#define TASK_DYING              16
+#define TASK_RUNNING             0
+#define TASK_INTERRUPTIBLE       1
+#define TASK_UNINTERRUPTIBLE     2
+#define TASK_STOPPED             4
+#define TASK_DYING               8
 
 #include <asm/uaccess.h> /* for KERNEL_DS */
 
index fedd5d9455543a98e647e41568d640af9f0b972c..d1ded5214ac6a785c573e2f01a9277b572d1ef57 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <asm/hypervisor-ifs/hypervisor-if.h>
+#include <asm/hypervisor-ifs/dom0_ops.h>
 #include <asm/ptrace.h>
 #include <asm/page.h>
 
@@ -262,10 +263,10 @@ static inline int HYPERVISOR_exit(void)
     return ret;
 }
 
-static inline int HYPERVISOR_dom0_op(void *dom0_op)
+static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
 {
     int ret;
-    op->interface_version = DOM0_INTERFACE_VERSION;
+    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
     __asm__ __volatile__ (
         TRAP_INSTR
         : "=a" (ret) : "0" (__HYPERVISOR_dom0_op),